/**
* @file StreamingSound.h
* @author Max Ocklind
* @version 2010-01-10
*
* <p>Based on the source and documentation by Jesse Maurais found at:
* <a href="http://www.devmaster.net/articles/openal-tutorials/lesson8.php">
* http://www.devmaster.net/articles/openal-tutorials/lesson8.php</a>
* </p>
**/


#if !defined(STREAMINGSOUND_H)
#define STREAMINGSOUND_H


/* includes */

#include <string>
#include <iostream>

#include <ogg/ogg.h>
#include <vorbis/vorbisfile.h>

#include "Sound.h"


/* defines */

// sound types
//#define NORMAL_SOUND		 1 in Sound.h
//#define STATIC_SOUND		 2 in StaticSound.h
#define   STREAMING_SOUND	 3

#define	  STREAM_BUFFER_SIZE (4 * 4096)
#define   NUM_STREAM_BUFFERS 5


/* classes */

class StreamingSound : public Sound
{
public:
	/**
	* Default constructor that calls the superclass default constructor.
	*/
	StreamingSound()
		: Sound()
	{
		// intentionallay left blank
	} /* StreamingSound() */
	
	/**
	* Constructor that calls the corresponding superclass constructor and generates the buffers used
	* for storing stream data.
	*
	* @param source the OpenAL sound source to be used by this <code>StreamingSound</code> object
	*/	
	StreamingSound(SoundSource source)
		: Sound(source)
	{
		reset(source);

		// generate buffers for streaming
		alGenBuffers(NUM_STREAM_BUFFERS, mBuffers);
		errCheck->checkALError("StreamingSound", "open (generate buffers)");
	} /* StreamingSOund(SoundSource source) */

	/**
	* Destructor that stops the sound and deletes the buffers used for storing stream data.
	*/
	~StreamingSound()
	{
		// unqueue buffers and release Ogg Vorbis stream
		mRelease();

		// delete buffers for streaming
		alDeleteBuffers(NUM_STREAM_BUFFERS, mBuffers);
		errCheck->checkALError("StreamingSound", "~StreamingSound (delete buffers)");
	} /* ~StreamingSound() */

	void play(std::string filePath, int priority, const char* cullType, ALfloat* position, ALfloat* velocity);
	void play(std::string filePath, int priority, const char* cullType, ALfloat* position, ALfloat* velocity, SFXFilter* filter, unsigned long timeLimit);
	void play(std::string filePath, int priority, const char* cullType, ALfloat* position, ALfloat* velocity, ALboolean loop, ALfloat pitch, ALfloat gain, ALfloat rolloffFactor, SFXFilter* filter, unsigned long timeLimit);

	virtual void play(SoundBuffer buffer, int priority, const char* cullType, ALfloat* position, ALfloat* velocity);
	virtual void play(SoundBuffer buffer, int priority, const char* cullType, ALfloat* position, ALfloat* velocity, SFXFilter* filter, unsigned long timeLimit);
	virtual void play(SoundBuffer buffer, int priority, const char* cullType, ALfloat* position, ALfloat* velocity, ALboolean loop, ALfloat pitch, ALfloat gain, ALfloat rolloffFactor, SFXFilter* filter, unsigned long timeLimit);

	virtual void setProperties(ALfloat* position, ALfloat* velocity, ALboolean loop, ALfloat pitch, ALfloat gain, ALfloat rolloffFactor);

	virtual void update();
	virtual void reset(SoundSource source);

protected:
	void			mOpen(std::string filePath);
    void			mRelease();
    bool			mPlayback();
	bool			mStream(SoundBuffer buffer);
    void			mEmpty();
	std::string		mErrorString(int code);
	
private:
    FILE*           mOggFile;
    OggVorbis_File  mOggStream;
	vorbis_info*    mVorbisInfo;
	std::string		mFilePath;

    SoundBuffer		mBuffers[NUM_STREAM_BUFFERS];
    ALenum			mFormat;

	bool			mLooping;
	bool			mStreamOpened;
	bool			mHasBegunBuffering;
}; /* StreamingSound */

#endif /* STREAMINGSOUND_H */